import pygame
import pyrr

from three.camera import Camera


class OrbitController:
    def __init__(self, camera: Camera, width: int, height: int):
        self.camera: Camera = camera
        self.width = width
        self.height = height
        self._is_down = False
        self._start_pos: tuple[int, int] = 0, 0

    def on_mouse_down(self, dt: float, wt: float, event):
        self._is_down = True
        self._start_pos = event.pos

    def on_mouse_up(self, dt: float, wt: float, event):
        self._is_down = False
        self._start_pos: tuple[int, int] = 0, 0

    def on_mouse_move(self, dt: float, wt: float, event):
        if not self._is_down:
            return
        current_pos = event.pos
        dx = current_pos[0] - self._start_pos[0]
        focus = self.camera.focus
        position = self.camera.get_position()
        translate1 = pyrr.Matrix44.from_translation(-focus)
        rotate_x = pyrr.Matrix44.from_y_rotation(dx / self.width * 20)
        translate2 = pyrr.Matrix44.from_translation(focus)
        position_vec4 = translate2 * rotate_x * translate1 * pyrr.Vector4((*position, 1))
        self.camera.set_position(position_vec4.xyz)
        self.camera.lookat(focus)
        self._start_pos = current_pos

    def update(self, dt: float, wt: float, events):
        for event in events:
            if event.type == pygame.MOUSEMOTION:
                self.on_mouse_move(dt, wt, event)
            elif event.type == pygame.MOUSEBUTTONDOWN:
                self.on_mouse_down(dt, wt, event)
            elif event.type == pygame.MOUSEBUTTONUP:
                self.on_mouse_up(dt, wt, event)